#ifndef STATSxx_STATISTICS_COVARIANCEFUNCTION_HPP
#define STATSxx_STATISTICS_COVARIANCEFUNCTION_HPP


// STL
#include <memory>                                // std::unique_ptr<>
#include <vector>                                // std::vector<>

// Boost
#include <boost/serialization/export.hpp>
#include <boost/serialization/serialization.hpp> // boost::serialization::
#include <boost/serialization/vector.hpp>        // serialize std::vector<>

// jScience
#include "jScience/linalg/Vector.hpp"            // Vector<>

// stats++
//#include "statsxx/statistics/covariance_functions.hpp"   // squared exponential


//=========================================================
// COVARIANCE FUNCTION
//=========================================================
class CovarianceFunction
{

public:

    CovarianceFunction();
    CovarianceFunction(const std::vector<double> &th);
    ~CovarianceFunction();

    virtual std::unique_ptr<CovarianceFunction> clone() const = 0;

    virtual double              cov(const Vector<double> &x1, const Vector<double> &x2) = 0;
    virtual std::vector<double> ddtheta(const Vector<double> &x1, const Vector<double> &x2);
    virtual Vector<double>      ddx(const Vector<double> &x, const Vector<double> &x2);

    int nhyperparameters();
    void assign_hyperparameters(const std::vector<double> &th);

    // NOTE: This needs to be public for the _GP package.
    std::vector<double> theta;

private:

    // ----- (Boost) SERIALIZATION -----
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(
                   Archive            &ar,
                   const unsigned int  version
                   )
    {
//        ar.template register_type<SquaredExponential>();

        ar & this->theta;
    }

};

BOOST_SERIALIZATION_ASSUME_ABSTRACT(CovarianceFunction);

//BOOST_CLASS_EXPORT_KEY(CovarianceFunction);

#include "statsxx/statistics/CovarianceFunction/CovarianceFunction.cpp"

//BOOST_CLASS_EXPORT(CovarianceFunction);
//BOOST_CLASS_EXPORT_KEY(CovarianceFunction);
//BOOST_CLASS_EXPORT_IMPLEMENT(CovarianceFunction);

#endif
